package data

import (
	"gitee.com/u-language/u-language/ucom/errcode"
)

// IsItARecursiveType 表示可能是递归类型
type IsItARecursiveType interface {
	My() string
	DepLen() int
	//Dependencies
	Dep(i int) IsItARecursiveType
}

// Check Including self 检查是否包含自身
func CheckIncludingSelf(typ IsItARecursiveType) (errcode.ErrCode, errcode.Msg) {
	depLen := typ.DepLen()
	if depLen == 0 {
		return errcode.NoErr, nil
	}
	my := typ.My()
	for i := 0; i < depLen; i++ {
		code, msg := checkIncludingSelf(my, typ.Dep(i)) //检查单个依赖项
		if code != errcode.NoErr {
			msg.Dep[0] = my
			return code, msg
		}
	}
	return errcode.NoErr, nil
}

func checkIncludingSelf(my string, dep IsItARecursiveType) (errcode.ErrCode, errcode.MsgRecursiveTypeErr) {
	depLen := dep.DepLen()
	if depLen == 0 {
		return errcode.NoErr, errcode.MsgRecursiveTypeErr{}
	}
	for i := 0; i < depLen; i++ {
		v := dep.Dep(i)
		if v == nil {
			continue
		}
		if my == v.My() { //如果发现自己包含自己
			return errcode.RecursiveTypeErr, errcode.NewMsgRecursiveTypeErr(my)
		}
		code, msg := checkIncludingSelf(my, v)
		if code != errcode.NoErr {
			//将当前依赖项添加到附加错误
			if msg.Dep[1] != v.My() {
				msg.Dep = append([]string{msg.Dep[0], v.My()}, msg.Dep[1:]...)
			}
			return code, msg
		}
	}
	return errcode.NoErr, errcode.MsgRecursiveTypeErr{}
}
